Function.RegisterNamespace("Test.System.IO");

[Fixture]
Test.System.IO.Path=function(){
    [Fixture]
    function Combine(){
        [Fact]
        function ThrowsIfPath1IsOmitted(){
            var expected="System.IO.Path.Combine: 'path1' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPath1IsUndefined(){
            var expected="System.IO.Path.Combine: 'path1' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPath1IsNull(){
            var expected="System.IO.Path.Combine: 'path1' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPath1IsNotConvertibleToString(){
            var expected="System.IO.Path.Combine: 'path1' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine({toString:null});
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPath2IsOmitted(){
            var expected="System.IO.Path.Combine: 'path2' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine("");
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPath2IsUndefined(){
            var expected="System.IO.Path.Combine: 'path2' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine("",undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPath2IsNull(){
            var expected="System.IO.Path.Combine: 'path2' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine("",null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPath2IsNotConvertibleToString(){
            var expected="System.IO.Path.Combine: 'path2' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.Combine("",{toString:null});
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsToStringMethodOnPath1(){
            var target={toString:function(){
                actual=true;
                return "";
            }};
            var actual=false;
            
            System.IO.Path.Combine(target,"");
            
            Assert.True(actual);
        }

        [Fact]
        function CallsToStringMethodOnPath2(){
            var target={toString:function(){
                actual=true;
                return "";
            }};
            var actual=false;
            
            System.IO.Path.Combine("",target);
            
            Assert.True(actual);
        }
        
        [Fact]
        function TrimsTrailingSeparatorFromPath1(){
            var target="target";
            var expected=target+System.IO.Path.DirectorySeparator+target;
            
            var actual=System.IO.Path.Combine(target+System.IO.Path.DirectorySeparator,target);

            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function TrimsLeadingSeparatorFromPath2(){
            var target="target";
            var expected=target+System.IO.Path.DirectorySeparator+target;
            
            var actual=System.IO.Path.Combine(target,System.IO.Path.DirectorySeparator+target);

            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function JoinsPath1AndPath2WithDirectorySeparator(){
            var target="expected";
            var expected=target+System.IO.Path.DirectorySeparator+target;
            
            var actual=System.IO.Path.Combine(target,target);

            Assert.Equal(expected,actual);
        }
    }
    
    [Fixture]
    function GetFileName(){
        [Fact]
        function ThrowsIfPathIsOmitted(){
            var expected="System.IO.Path.GetFileName: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFileName();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsUndefined(){
            var expected="System.IO.Path.GetFileName: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFileName(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsNull(){
            var expected="System.IO.Path.GetFileName: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFileName(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPathIsNotConvertibleToString(){
            var expected="System.IO.Path.GetFileName: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFileName({toString:null});
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsToStringMethodOnPath(){
            var target={toString:function(){
                actual=true;
                return "";
            }};
            var actual=false;
            
            System.IO.Path.GetFileName(target);
            
            Assert.True(actual);
        }
        
        [Fact]
        function ReturnsFullSegmentIfNoDirectorySeparator(){
            var expected="expected";
            
            var actual=System.IO.Path.GetFileName(expected);

            Assert.Equal(expected,actual);
        }
        
        
        [Fact]
        function ReturnsSegmentAfterDirectorySeparator(){
            var expected="expected";
            
            var actual=System.IO.Path.GetFileName("target"+System.IO.Path.DirectorySeparator+expected);

            Assert.Equal(expected,actual);
        }
    }
    
    [Fixture]
    function GetFullPath(){
        [Fact]
        function ThrowsIfPathIsOmitted(){
            var expected="System.IO.Path.GetFullPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFullPath();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsUndefined(){
            var expected="System.IO.Path.GetFullPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFullPath(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsNull(){
            var expected="System.IO.Path.GetFullPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFullPath(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPathIsNotConvertibleToString(){
            var expected="System.IO.Path.GetFullPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetFullPath({toString:null});
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsToStringMethodOnPath(){
            var target={toString:function(){
                actual=true;
                return "";
            }};
            var actual=false;
            
            System.IO.Path.GetFullPath(target);
            
            Assert.True(actual);
        }

        [Fact]
        function ReturnsPathIfProtocolMarkerFound(){
            var expected="http://expected";
        
            var actual=System.IO.Path.GetFullPath(expected);
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CombinesPathWithRootIfProtocolMarkerNotFound(){
            var target="target";
            var targetRoot="http://root";
            var targetSeparator=System.IO.Path.DirectorySeparator;
            System.IO.Path.DirectorySeparator='/';
            var expected=targetRoot+System.IO.Path.DirectorySeparator+target;
            System.IO.Path.SetRoot(targetRoot);
        
            var actual=System.IO.Path.GetFullPath(target);
            System.IO.Path.DirectorySeparator=targetSeparator;
            
            Assert.Equal(expected,actual);
        }
    }
    
    [Fixture]
    function GetPath(){
        [Fact]
        function ThrowsIfPathIsOmitted(){
            var expected="System.IO.Path.GetPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetPath();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsUndefined(){
            var expected="System.IO.Path.GetPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetPath(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsNull(){
            var expected="System.IO.Path.GetPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetPath(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPathIsNotConvertibleToString(){
            var expected="System.IO.Path.GetPath: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.GetPath({toString:null});
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsToStringMethodOnPath(){
            var target={toString:function(){
                actual=true;
                return "";
            }};
            var actual=false;
            
            System.IO.Path.GetPath(target);
            
            Assert.True(actual);
        }
        
        [Fact]
        function TrimsDirectorySeparatorFromEnd(){
            var expected="expected";
         
            var actual=System.IO.Path.GetPath(expected+System.IO.Path.DirectorySeparator);
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ReturnsPath(){
            var expected="expected";
            
            var actual=System.IO.Path.GetPath(expected);
            
            Assert.Equal(expected,actual);
        }
    }
    
    [Fixture]
    function GetRoot(){
        [Fact]
        function ReturnsSpecifiedRoot(){
            var expected="root"+System.IO.Path.DirectorySeparator;
            
            System.IO.Path.SetRoot(expected);
            var actual=System.IO.Path.GetRoot();
        
            Assert.Equal(expected,actual);
        }
    }
    
    [Fixture]
    function SetRoot(){
         [Fact]
        function ThrowsIfPathIsOmitted(){
            var expected="System.IO.Path.SetRoot: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.SetRoot();
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsUndefined(){
            var expected="System.IO.Path.SetRoot: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.SetRoot(undefined);
            });
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function ThrowsIfPathIsNull(){
            var expected="System.IO.Path.SetRoot: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.SetRoot(null);
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function ThrowsIfPathIsNotConvertibleToString(){
            var expected="System.IO.Path.SetRoot: 'path' must be convertible to String.";
            
            var actual=Record.Exception(function(){
                System.IO.Path.SetRoot({toString:null});
            });
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function CallsToStringMethodOnPath(){
            var target={toString:function(){
                actual=true;
                return "";
            }};
            var actual=false;
            
            System.IO.Path.SetRoot(target);
            
            Assert.True(actual);
        }
        
        [Fact]
        function NormalizesBackAndForwardSlashesToDirectorySeparator(){
            var target="target\\target/target";
            var expected="target-target-target-";
            var targetSeparator=System.IO.Path.DirectorySeparator;
            System.IO.Path.DirectorySeparator='-';
            
            System.IO.Path.SetRoot(target);
            var actual=System.IO.Path.GetRoot();
            System.IO.Path.DirectorySeparator=targetSeparator;
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function TrimsFileNameByExtensionTokenIfFoundInLastSegment(){
            var target="target/target/target.target";
            var expected=["target","target",""].join(System.IO.Path.DirectorySeparator);
            
            System.IO.Path.SetRoot(target);
            var actual=System.IO.Path.GetRoot();
            
            Assert.Equal(expected,actual);
        }

        [Fact]
        function IgnoresExtensionTokenInDirectoryName(){
            var target="target/target/target.target/target";
            var expected=["target","target","target.target","target",""].join(System.IO.Path.DirectorySeparator);

            System.IO.Path.SetRoot(target);
            var actual=System.IO.Path.GetRoot();

            Assert.Equal(expected,actual);
        }

        [Fact]
        function CallsDirectoryExistsToCheckPathWithDirectorySeparatorInLastSegment(){
            var target="target\\target\\target.target";
            var targetExists=System.IO.Directory.Exists;
            System.IO.Directory.Exists=function(){
                actual=true;
            }
            var actual=false;
            
            System.IO.Path.SetRoot(target);
            System.IO.Path.GetRoot();
            
            Assert.True(actual);
        }

        [Fact]
        function IgnoresLastSegmentWhenDirectoryExistsReturnsTrue(){
            var target="target/target/target.target";
            var expected=["target","target","target.target",""].join(System.IO.Path.DirectorySeparator);
            var targetExists=System.IO.Directory.Exists;
            System.IO.Directory.Exists=function(){
                return true;
            }
            
            System.IO.Path.SetRoot(target);
            var actual=System.IO.Path.GetRoot();
            System.IO.Directory.Exists=targetExists;
            
            Assert.Equal(expected,actual);
        }
        
        [Fact]
        function SetsPathPlusDirectorySeparatorIfDirectorySeparatorNotFound(){
            var target="target";
            var expected="target"+System.IO.Path.DirectorySeparator;
            
            System.IO.Path.SetRoot(target);
            var actual=System.IO.Path.GetRoot();
            
            Assert.Equal(expected,actual);
        }
    }   
}